package mylibrary.thread.threadpool;

import java.util.Random;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

public class LogThreadPool extends ThreadPoolExecutor {

	public LogThreadPool(int corePoolSize, int maximumPoolSize,
			long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
		super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
	}
	
	private final AtomicInteger numTasks = new AtomicInteger();
	private final AtomicLong totalTimes = new AtomicLong();
	private ThreadLocal<Long> startTime = new ThreadLocal<Long>();
	
	public static void main(String[] args) {
		
		ThreadPoolExecutor pool = new LogThreadPool(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue());
		
		Runnable task = new Runnable(){
			
			public void run(){
				System.out.println(Thread.currentThread().getName() + " task is executing");
				try{
					int rand = new Random().nextInt(1000);
					Thread.sleep(rand);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		};
		
		int ThreadNum = 5;
		for(int i=0; i<ThreadNum; i++) {
			pool.execute(task);
		}
		pool.shutdown();
	}
	
	protected void beforeExecute(Thread t, Runnable r) {
		super.beforeExecute(t, r);
		System.out.println(t.getName() + " before task execute");
		startTime.set(System.currentTimeMillis());
	}
	
	protected void afterExecute(Runnable r, Throwable t) {
		super.afterExecute(r, t);
		long endTime = System.currentTimeMillis();
		long taskTime = endTime - startTime.get();
		numTasks.incrementAndGet();
		System.out.println(Thread.currentThread().getName() + " task executed time:" + taskTime);
		totalTimes.addAndGet(taskTime);
	}
	
	protected void terminated() {
		super.terminated();
		System.out.println("All tasks finished");
		System.out.println("Tasks number: " + numTasks);
		System.out.println("Total executed time:" + totalTimes.get());
	}
	

}
